package xyz.msj.hrm.service.impl;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import xyz.msj.hrm.constant.SMSConstant;
import xyz.msj.hrm.dto.SendSMSDto;
import xyz.msj.hrm.excptions.GlobalException;
import xyz.msj.hrm.feign.client.RedisFeignClient;
import xyz.msj.hrm.properties.ConfigProperties;
import xyz.msj.hrm.service.IVerifyCodeService;
import xyz.msj.hrm.util.AjaxResult;
import xyz.msj.hrm.util.StrUtils;
import xyz.msj.hrm.util.VerifyCodeUtils;
import xyz.msj.hrm.vo.SMSCodeSendVo;

import java.io.IOException;
import java.util.Date;

/**
 * 图片验证码生成service
 */
@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    @Autowired
    private RedisFeignClient redisFeignClient;
    @Autowired
    private ConfigProperties configProperties;

    /**
     * 图片验证码生成
     * @param key  前台生成的uuid  用来存储到redis中作为key
     * @return
     */
    @Override
    public String imageCode(String key){

        //1、判断获取到的key
        if (StringUtils.isEmpty(key)) {
            throw new GlobalException("请重新刷新，获取验证码验证码");
        }

        //2、获取验证码
        String verifyCode = StrUtils.getComplexRandomString(configProperties.getImageCode().getLength());
        //将验证码转换为json字符串
        //String jsonVerifyCode = JSON.toJSONString(verifyCode);
        //3、存储到redis
        redisFeignClient.setex(key,configProperties.getImageCode().getExpire(),verifyCode);
        //4、将验证码加入到图片中
        try {
            return VerifyCodeUtils.verifyCode(
                    configProperties.getImageCode().getWidth(),
                    configProperties.getImageCode().getHeight(),
                    verifyCode);
        } catch (IOException e) {
            e.printStackTrace();
            throw new GlobalException("图片验证码创建失败");
        }
    }

    /**
     * 短信生成验证码
     * @return
     */
    @Override
    public void sendSmsCode(SendSMSDto sendSMSDto) {
        //获取到图片验证redis key 值
        String imageCodeKey = sendSMSDto.getImageCodeKey();
        //获取图片验证码
        String imageCode = sendSMSDto.getImageCode();
        //获取手机号
        String mobile = sendSMSDto.getMobile();
        //参数校验
        cheakParam(imageCodeKey, imageCode, mobile);
        //获取当前时间
        Date nowDate = new Date();
        //手机验证码
        String SMSCodeValue = null;
        //获取短信验证码
        SMSCodeValue = getSMSCode(mobile, nowDate);
        //将验证码转换为json字符串
        String jSONString = JSON.toJSONString(new SMSCodeSendVo(SMSCodeValue, nowDate));

        //String key = String.format(SMSConstant.SMS_PHONE_REG, mobile);

        //3、存储到redis
        AjaxResult setex = redisFeignClient.setex(SMSConstant.SMS_PHONE_REG + mobile, configProperties.getSendSmsCode().getExpire(), jSONString);
        if (!setex.isSuccess()){
            throw new GlobalException("短信验证码发送失败！请刷新重新发送");
        }
        //5.调用短信网关发送手机验证码
        String sendMessage =String.format(configProperties.getSendSmsCode().getContext(),SMSCodeValue,configProperties.getSendSmsCode().getExpire()/60) ;

        System.out.println(sendMessage);
        //假如网建返回的错误码
        //int result = -1;
        //调用错误处理方法
        //WebChineseSMSResult.assertErrorCode(String.valueOf(result));
        //发送短信，处理结果
        //SmsUtil.sendMessage(mobile,sendMessage);
        //6.存储验证码的发送记录到Mysql（ip,手机号，验证码，发送时间，状态） ：省略
    }

    private String getSMSCode(String mobile, Date nowDate) {
        String SMSCodeValue;//获取上一次验证码发送记录
        //手机验证码在redis中存储的key REG:PHONE:18482203513 格式 //查询是否已经发送过短信验证码
        AjaxResult smsCodeJson = redisFeignClient.get(SMSConstant.SMS_PHONE_REG + mobile);
        //判断redis中是否有值，判断短信验证码是否过期验证码
        if (smsCodeJson.isSuccess() && smsCodeJson.getResultObj() != null) {
            //如果上次有
            SMSCodeSendVo lastSendVo = JSON.parseObject(smsCodeJson.getResultObj().toString(), SMSCodeSendVo.class);
            //3.1.1.判断时候是否过了重发时间 ：当前时间 - 上一次发送时间 > 60s
            if ((nowDate.getTime() - lastSendVo.getSendTime().getTime())/1000 < configProperties.getSendSmsCode().getResendTime()) {
                throw new  GlobalException("发送频繁，请稍后重试！");
            }
            //3.1.3.如果过了重发时间 ，获取上一次验证码的值
            SMSCodeValue = lastSendVo.getCode();
        }else {
            //上次没有
            //2、获取短信验证码
            SMSCodeValue = StrUtils.getComplexRandomString(configProperties.getSendSmsCode().getLength());
        }
        return SMSCodeValue;
    }

    private void cheakParam(String imageCodeKey, String imageCode, String mobile) {
        //图片验证码值判断
        if (StringUtils.isEmpty(imageCodeKey)) {
            throw new GlobalException("图片验证redis中 key 值为空！");
        }
        //图片验证码判断
        if (StringUtils.isEmpty(imageCode)) {
            throw new GlobalException("图片验证码值为空！");
        }
        //手机号判断
        if (StringUtils.isEmpty(mobile)) {
            throw new GlobalException("手机号为空！");
        }
        //对输入的验证码进行判读是否输入正确
        //根据图片验证码key，查询value进行比较
        AjaxResult imageCodeJSon = redisFeignClient.get(imageCodeKey);
        //判断图片验证码是否失效
        if (!imageCodeJSon.isSuccess() || imageCodeJSon.getResultObj() == null) {
            throw new GlobalException("图片验证码已经过期或无效，请重新输入！");
        }
        //判断值是否相等
        if (!imageCodeJSon.getResultObj().toString().toUpperCase().equals(imageCode.toUpperCase())) {
            throw new GlobalException("输入的图片验证码不正确！请重新输入");
        }
    }
}
